# !/usr/bin/python
# -*- coding: UTF-8 -*-
#https://github.com/IanHarvey/bluepy/blob/master/bluepy

import os
import sys
import shutil
import datetime
import binascii
import bluepy
import bluetooth
import thread
import struct
import tty,termios
from time import ctime,sleep

exitFlag = False
#getdatacmd = "\xBE\xBE\x21\x01\x07\x07\x75\x7A\x46\x1D\x09\x0E\xED\xED" #len=14

def printusage():
    print "Usage:"
    print "     sudo python blue_conn.py [-h help]" 
    print "                              [-i hci dev number]"
    print "                              [-t timeout]"
    print "                              [mac 00:00:00:00:00:00]"
    print "                              [mactype \"public\"/\"random\"]"
    print "                              [uuid 00000000-0000-...]"
    print "                              [chid 00000000-0000-...]"
    print "                              [feedp \"time(170607185600)\" \"length(10000)\"]"
    print "                              [-s Save a file and Remarks]"
    print "     sudo python blue_conn.py mac 00:0B:57:05:AB:FE uuid 1101 chid 8888 -i hci0 -s 10_00_no -t 60"
    return;

def requestParameter(tar,par):
    pa = par.split()
    t=map(int,[pa[0][i:i+2] for i in xrange(0, len(pa[0]), 2)])
    length = int(pa[1])
    tm = ((t[0] - 10) << 26) + ((t[1] - 1) << 22) + (t[2] << 17) + ((t[3] - 1) << 12) + ((t[4] - 1) << 6) + (t[5])
    tar[-5] = ((tm >> 24) & 0xff) 
    tar[-6] = (tm >> 16) & 0xff 
    tar[-7] = (tm >> 8) & 0xff 
    tar[-8] = (tm >> 0) & 0xff 
    tar[-3] = length >> 8
    tar[-4] = length & 0xff
    return tar 

def connect(mac,mactype="public",uuid=None,chid=None):
    #start connect 
    if not mac is None:
        print "Connecting to mac:",mac,"mactype:",mactype
        con = bluetooth.leconnect2mac(mac,mactype)
        if not con is None:
            print "Connected"
        else:
            print "Con't connect to target"
            return None 
        if uuid is None:
            for svc in con.services:
                print(str(svc), ":")
                for ch in svc.getCharacteristics():
                    print("    {}, hnd={}, supports {}".format(ch, hex(ch.handle), ch.propertiesToString()))
                    chName = bluepy.btle.AssignedNumbers.getCommonName(ch.uuid)
                    if (ch.supportsRead()):
                        try:
                            print("    ->", repr(ch.read()))
                        except BTLEException as e:
                            print("    ->", e)
        else:
            svc = con.getServiceByUUID(uuid)
            ch = svc.getCharacteristics()  
            if chid is None:
                for cch in ch:
                    print("{}, hnd={}, supports {}".format(cch, hex(cch.handle), cch.propertiesToString()))
                    if (cch.supportsRead()):
                        try:
                            print(" ->",cch.read())
                        except BTLEException as e:
                            print(" ->", e)
            else:
                for cch in ch: 
                    if (bluepy.btle.UUID(chid) == cch.uuid): 
                        return con,cch.valHandle,cch.propertiesToString()
    else:
        print "please input target mac"
        printusage()  
    return None

def turn_char_notify(conn,charhandle=None,supports=None):
    if "NOTIFY" in supports.upper():
        #Turn on notifications
        conn.writeCharacteristic(charhandle + 1,struct.pack('<bb', 0x01, 0x00))
        return True
    else:
        return False

def conn_read_whitcharhandle(conn,charhandle=None,supports=None):
    if not charhandle is None and not supports is None:
        if "READ" in supports.upper():
            read = conn.readCharacteristic(charhandle)
            return read
            #print "read-> ",("->",read),map(ord,read)
        elif "NOTIFY" in supports.upper():
            #res = conn.waitForNotifications(1)
            savedStdout = sys.stdout  #保存标准输出流
            with open('notifylog.log', 'w+') as file:
                try:
                    sys.stdout = file  #标准输出重定向至文件
                    res = conn._getResp(['ntfy'], 1)
                    sys.stdout = savedStdout  #恢复标准输出流
                    if res != None:
                        return res
                    else:
                        sleep(1)
                        #print "notify-> ",res['d']
                except:
                    sys.stdout = savedStdout  #恢复标准输出流

        elif "INDICATE" in supports.upper():
            #res = conn.waitForNotifications(1)
            savedStdout = sys.stdout  #保存标准输出流
            with open('notifylog.log', 'w+') as file:
                try:
                    sys.stdout = file  #标准输出重定向至文件
                    res = conn._getResp(['ind'], 1)
                    sys.stdout = savedStdout  #恢复标准输出流
                    if res != None:
                        return res
                        #print "ind-> ",res['d']
                except:
                    sys.stdout = savedStdout  #恢复标准输出流
        else:
            return None
    else:
        print "Not find target characteristic"
        return None

def conn_write_whitcharhandle(conn,charhandle=None,supports=None,senddata=None,resp=False):
    if not charhandle is None and not supports is None and "WRITE" in supports.upper():
        if not senddata is None:
            #print "write-> ","\"",senddata,"\"",",","\"",binascii.b2a_hex(senddata).decode('utf-8'),"\""
            conn.writeCharacteristic(charhandle,senddata,resp)
    else:
        print "Not find target characteristic"

def get_key_boardinput():
    instr = raw_input()
    return instr

def get_key_boardinput_thread():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    while not exitFlag is True: 
        tty.setraw(fd)
        ch = sys.stdin.read(1)
        #print type(ch),len(ch)
        if ord(ch[0]) == (ord('a') & 0x1f):
            #print 'ctrl+a',ord(ch[0]),
            pass
        elif ord(ch[0]) == (ord('x') & 0x1f):
            #print 'ctrl+x',ord(ch[0]),
            pass
        elif ord(ch[0]) == (ord('z') & 0x1f):
            #print 'ctrl+z',ord(ch[0]),
            pass
        elif ord(ch[0]) == (ord('q') & 0x1f):
            #print 'ctrl+q',ord(ch[0]),
            exitFlag = True 
            break; 
        else:
            print '\b%c'%ch[0],
    termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)

def parse_keyboard_input(inputstr):
    global exitFlag
    if len(inputstr) == 0:
        return None
    cmd = inputstr.split()    
    if 'quit' in cmd and len(cmd) == 1:
        exitFlag = True 
        return None
    elif 'request' in cmd and len(cmd) == 4:
        senddata = [0xBE,0xBE,0x21,0x01,0x07,0x07,0x44,0x45,0x54,0x1D,0x09,0x0E,0xED,0xED] #len=14
        senddata = requestParameter(senddata,cmd[(cmd.index("feedp") + 1)] + " " + cmd[(cmd.index("feedp") + 2)])
        return "".join(map(chr,senddata))
    elif 'resetcon' in cmd:
        return None
    else:
        return inputstr
    
def conn_read_thread(conn,charhandle=None,supports=None):
    global exitFlag
    end = ['\xbe\xbe\x11\x00\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xed\xed']
    counter = 0
    length = 0
    turn_char_notify(conn,charhandle,supports)
    while not exitFlag is True: 
        read = conn_read_whitcharhandle(conn,charhandle,supports)
        if not read is None:
            print "notify-> ",read['d']
            length = length + len(read['d'][0])
            if read['d'] == end:
                exitFlag = True
                print "recv counter:",((counter+1) * 2),"length:",length
            counter = counter + 1

def conn_write_formkeyboard_thread(conn,charhandle=None,supports=None):
    global exitFlag
    senddata = None
    while not exitFlag is True: 
        senddata = get_key_boardinput()
        senddata = parse_keyboard_input(senddata)
        if not senddata is None:
            try:
                print "write-> ","\"",senddata,"\"",",","\"",binascii.b2a_hex(senddata).decode('utf-8'),"\""
                conn_write_whitcharhandle(conn,charhandle,supports,senddata,True)
            except:
                pass



if __name__ == '__main__':

    charhandle = None
    supports = None
    conn = None
    #requestcmd = [0xBE,0xBE,0x21,0x01,0x07,0x07,0x44,0x45,0x54,0x1D,0x09,0x0E,0xED,0xED] #len=14
    requestcmd = [0xBE,0xBE,0x21,0x01,0x07,0x07,0x44,0x55,0x56,0x1D,0x09,0x8E,0xED,0xED] #len=14

    if "-h" in sys.argv:
        printusage()  
        exit()
    if "mac" in sys.argv:
        mac = sys.argv[(sys.argv.index("mac") + 1)]        
    else:
        mac = None 
    if "mactype" in sys.argv:
        mactype = sys.argv[(sys.argv.index("mactype") + 1)]
        if mactype == "public" or mactype == "random":
            pass
        else:
            mactype = "public"
    else:
        mactype = "public"
    if "uuid" in sys.argv:
        uuid = sys.argv[(sys.argv.index("uuid") + 1)]        
    else:
        uuid = None 
    if "chid" in sys.argv:
        chid = sys.argv[(sys.argv.index("chid") + 1)]        
    else:
        chid = None 
    if "feedp" in sys.argv:
        requestcmd = requestParameter(requestcmd,sys.argv[(sys.argv.index("feedp") + 1)] + " " + sys.argv[(sys.argv.index("feedp") + 2)])

    print map(hex,requestcmd)

    #print mac,mactype,uuid,bluepy.btle.UUID(uuid)

    #start connect
    con=connect(mac,mactype,uuid,chid)
    if con is None:
        print "Con't Connect"
        exit()
    conn = con[0]
    charhandle = con[1]
    supports = con[2]
    conn.setMTU(250)

    #if "feedp" in sys.argv:
    conn_write_whitcharhandle(conn,charhandle,supports,"".join(map(chr,requestcmd)),True)
    thread.start_new_thread(conn_read_thread,(conn,charhandle,supports))
    thread.start_new_thread(conn_write_formkeyboard_thread,(conn,charhandle,supports))

    while not exitFlag is True: 
        pass

    conn.disconnect()

    print "Disconnect"

    exit()




